home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / SpriteFight 2002 v2.0a1 / StefSpriteStuff.c < prev    next >
Text File  |  1996-05-01  |  17KB  |  567 lines

  1. // StefSpriteStuff.c  by Stefan Sinclair ©1995-1996 All Rights Reserved
  2.  
  3. #include "Spritez.h"
  4. #include "SpriteCicnNumbers.h"
  5. #include "SpriteError.h"
  6. #include "SpriteSecretCodes.h"
  7.  
  8. #define kErrorAlertID        150
  9. #define kEmptyString        "\p"
  10.  
  11. extern SpriteGameRec spriteGame;
  12. extern SndChannelPtr gSoundChanP1, gSoundChanP2, gSoundChanGame;
  13. extern Handle    gP1SoundH[kNumSpriteSounds], gP2SoundH[kNumSpriteSounds];
  14. extern RgnHandle gWorkRgn; // defined in Spritez.c
  15. extern PixPatHandle gLifePixPatH;
  16. extern Point    player1TopLeft, projectile1TopLeft;
  17. extern Point    player2TopLeft, projectile2TopLeft;
  18. extern CWindowPtr    gWindowP;
  19. extern Boolean gQT, gSoundOff, gSoundMax, gSoundMegaMax;
  20. extern short gSpriteHeight, gSpriteWidth;
  21. extern Rect gPlayer1DamageRect, gPlayer2DamageRect;
  22. extern Boolean gSecretCode[kNumSecretCodes];
  23.  
  24. /** CombatMoveProc **/
  25. // Here, reset sprite frame range as necessary depending on current & previous actions.
  26. SW_FUNC void CombatMoveProc(SpritePtr srcSpriteP, Point* spritePoint)
  27. {
  28.     unsigned char    *spriteDataPtr; // use as an array of 8 u. chars.
  29.     Boolean bSpriteAlive;
  30.     
  31.     // Access sprite's userData
  32.     spriteDataPtr = (unsigned char *)&srcSpriteP->userData;
  33.     // Assign the spritePoint to the correct sprite
  34.     switch(spriteDataPtr[kSpriteIDNum])
  35.     {
  36.         case kPlayer1Sprite:
  37.         case kComputer1Sprite:
  38.             player1TopLeft = *spritePoint;
  39.             break;
  40.         case kPlayer2Sprite:
  41.         case kComputer2Sprite:
  42.             player2TopLeft = *spritePoint;
  43.             break;
  44.         default:
  45.             DoError(kUnknownSpriteInGame, TRUE);
  46.             break;
  47.     }
  48.     
  49.     // Is the sprite still alive after this round of events?
  50.     bSpriteAlive = PlayerStatusCheck(srcSpriteP, spritePoint);
  51.     if(spriteDataPtr[kSpriteIDNum] == kPlayer1Sprite ||
  52.         spriteDataPtr[kSpriteIDNum] == kComputer1Sprite)
  53.     {
  54.         gPlayer1DamageRect.left = kP1LifeRectLeft + spriteDataPtr[kSpriteLife] - kSpriteMinLife;
  55.         FillCRect(&gPlayer1DamageRect, gLifePixPatH);
  56.     }
  57.     else
  58.     {
  59.         gPlayer2DamageRect.left = kP2LifeRectLeft + spriteDataPtr[kSpriteLife] - kSpriteMinLife;
  60.         FillCRect(&gPlayer2DamageRect, gLifePixPatH);
  61.     }
  62.     
  63.     // hit bottom - CHECKED IN GRAVITY CHECK
  64.     // hit left wall
  65.     if (srcSpriteP->destFrameRect.left <= srcSpriteP->moveBoundsRect.left)
  66.     {
  67.         srcSpriteP->horizMoveDelta = kMaxSpeed/2;
  68.         spritePoint->h = srcSpriteP->moveBoundsRect.left + 1;
  69.     }
  70.     // hit right wall
  71.     if (srcSpriteP->destFrameRect.right >= srcSpriteP->moveBoundsRect.right)
  72.     {
  73.         srcSpriteP->horizMoveDelta = -kMaxSpeed/2;
  74.         spritePoint->h = srcSpriteP->moveBoundsRect.right - gSpriteWidth - 1;
  75.     }
  76. }
  77.  
  78. /** ProjectileMoveProc **/
  79. // Here, reset sprite frame range as necessary depending on current & previous actions.
  80. SW_FUNC void ProjectileMoveProc(SpritePtr srcSpriteP, Point* spritePoint)
  81. {
  82.     unsigned char    *spriteDataPtr; // use as an array of 8 u. chars.
  83.     Boolean visible;
  84.     
  85.     // Access sprite's userData
  86.     spriteDataPtr = (unsigned char *)&srcSpriteP->userData;
  87.     
  88.     visible = ProjectileStatusCheck(srcSpriteP, spritePoint);
  89.     if(!visible)
  90.     {
  91.         srcSpriteP->horizMoveDelta = 0;
  92.         srcSpriteP->vertMoveDelta = 0;
  93.         SWSetSpriteVisible(srcSpriteP, FALSE);
  94.     }
  95.     // hit left wall
  96.     else if (srcSpriteP->destFrameRect.left <= srcSpriteP->moveBoundsRect.left)
  97.     {
  98.         srcSpriteP->horizMoveDelta = 0;
  99.         srcSpriteP->vertMoveDelta = 0;
  100.         spriteDataPtr[kCurrentAction] = aProjectileIdle;
  101.         SWSetSpriteVisible(srcSpriteP, FALSE);
  102.     }
  103.     // hit right wall
  104.     else if (srcSpriteP->destFrameRect.right >= srcSpriteP->moveBoundsRect.right)
  105.     {
  106.         srcSpriteP->horizMoveDelta = 0;
  107.         srcSpriteP->vertMoveDelta = 0;
  108.         spriteDataPtr[kCurrentAction] = aProjectileIdle;
  109.         SWSetSpriteVisible(srcSpriteP, FALSE);
  110.     }
  111.     // hit bottomwall
  112.     else if (srcSpriteP->destFrameRect.bottom > srcSpriteP->moveBoundsRect.bottom)
  113.     {
  114.         srcSpriteP->horizMoveDelta = 0;
  115.         srcSpriteP->vertMoveDelta = 0;
  116.         spriteDataPtr[kCurrentAction] = aProjectileIdle;
  117.         SWSetSpriteVisible(srcSpriteP, FALSE);
  118.     }
  119.     // hit top wall
  120.     else if (srcSpriteP->destFrameRect.top <= srcSpriteP->moveBoundsRect.top)
  121.     {
  122.         srcSpriteP->horizMoveDelta = 0;
  123.         srcSpriteP->vertMoveDelta = 0;
  124.         spriteDataPtr[kCurrentAction] = aProjectileIdle;
  125.         SWSetSpriteVisible(srcSpriteP, FALSE);
  126.     }
  127. }
  128.  
  129. // CombatSpriteCollideProc----------------------------------------------------------------
  130. void CombatSpriteCollideProc(SpritePtr srcSpriteP,SpritePtr dstSpriteP,Rect* sectRect)
  131. {
  132.     register short tempDelta;
  133.     Rect rgnRect;
  134.     unsigned char    *srcSpriteDataPtr,*dstSpriteDataPtr; // use as an array of 8 u. chars.
  135.     short srcDrxn, dstDrxn, damage = 0;
  136.     Boolean    dstSpriteHit = FALSE, srcSpriteHit = FALSE, somebodyHit;
  137.     static Boolean flipFlop; // to counter the player 1/2 advantage
  138.     
  139.     // Access sprite's userData
  140.     srcSpriteDataPtr = (unsigned char *)&srcSpriteP->userData;
  141.     dstSpriteDataPtr = (unsigned char *)&dstSpriteP->userData;
  142.     
  143.     // If both sprites use the same collision routine (this one),ignore the second collision.
  144.     if ((!srcSpriteP->isVisible || !dstSpriteP->isVisible) ||
  145.         ((srcSpriteP->spriteCollideProc == dstSpriteP->spriteCollideProc) &&
  146.         (srcSpriteP > dstSpriteP)))
  147.         return;
  148.  
  149.     rgnRect = (**srcSpriteP->curFrameP->maskRgn).rgnBBox;
  150.  
  151.     // move the mask region to the new sprite location
  152.     OffsetRgn(srcSpriteP->curFrameP->maskRgn,
  153.                 (srcSpriteP->destFrameRect.left - rgnRect.left) +
  154.                 srcSpriteP->curFrameP->offsetPoint.h,
  155.                 (srcSpriteP->destFrameRect.top - rgnRect.top) +
  156.                 srcSpriteP->curFrameP->offsetPoint.v);
  157.  
  158.     rgnRect = (**dstSpriteP->curFrameP->maskRgn).rgnBBox;
  159.  
  160.     // move the mask region to the new sprite location
  161.     OffsetRgn(dstSpriteP->curFrameP->maskRgn,
  162.                 (dstSpriteP->destFrameRect.left - rgnRect.left) +
  163.                 dstSpriteP->curFrameP->offsetPoint.h,
  164.                 (dstSpriteP->destFrameRect.top - rgnRect.top) +
  165.                 dstSpriteP->curFrameP->offsetPoint.v);
  166.  
  167.     SectRgn(srcSpriteP->curFrameP->maskRgn, dstSpriteP->curFrameP->maskRgn, gWorkRgn);
  168.  
  169.     if (!EmptyRgn(gWorkRgn)) // There is an overlap
  170.     {
  171.         Point sPt;
  172.         Boolean srcSide;
  173.         
  174.         // A sprite's projectile cannot damage him or herself
  175.         // Player 1
  176.         if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer1Sprite) &&
  177.             (dstSpriteDataPtr[kSpriteIDNum] == kPlayer1ProjectileSprite))
  178.             return;
  179.         if((srcSpriteDataPtr[kSpriteIDNum] == kComputer1Sprite) &&
  180.             (dstSpriteDataPtr[kSpriteIDNum] == kPlayer1ProjectileSprite))
  181.             return;
  182.         if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer1ProjectileSprite) &&
  183.             (dstSpriteDataPtr[kSpriteIDNum] == kPlayer1Sprite))
  184.             return;
  185.         if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer1ProjectileSprite) &&
  186.             (dstSpriteDataPtr[kSpriteIDNum] == kComputer1Sprite))
  187.             return;
  188.         // Player 2
  189.         if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer2Sprite) &&
  190.             (dstSpriteDataPtr[kSpriteIDNum] == kPlayer2ProjectileSprite))
  191.             return;
  192.         if((srcSpriteDataPtr[kSpriteIDNum] == kComputer2Sprite) &&
  193.             (dstSpriteDataPtr[kSpriteIDNum] == kPlayer2ProjectileSprite))
  194.             return;
  195.         if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer2ProjectileSprite) &&
  196.             (dstSpriteDataPtr[kSpriteIDNum] == kPlayer2Sprite))
  197.             return;
  198.         if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer2ProjectileSprite) &&
  199.             (dstSpriteDataPtr[kSpriteIDNum] == kComputer1Sprite))
  200.             return;
  201.         
  202.         // Where am I?
  203.         switch(srcSpriteDataPtr[kSpriteIDNum])
  204.         {
  205.             case kPlayer1Sprite:
  206.             case kComputer1Sprite:
  207.                 sPt = player1TopLeft;
  208.                 break;
  209.             case kPlayer2Sprite:
  210.             case kComputer2Sprite:
  211.                 sPt = player2TopLeft;
  212.                 break;
  213.             case kPlayer1ProjectileSprite:
  214.                 sPt = projectile1TopLeft;
  215.                 break;
  216.             case kPlayer2ProjectileSprite:
  217.                 sPt = projectile2TopLeft;
  218.                 break;
  219.         }
  220.         // Which drxn to go if hit?
  221.         srcSide = GetSpriteSide(srcSpriteDataPtr);
  222.         if(srcSide == kLeftSide)
  223.         {
  224.             srcDrxn = -2; // I go left
  225.             dstDrxn = 2; // You go right
  226.         }
  227.         else
  228.         {
  229.             srcDrxn = 2; // I go right
  230.             dstDrxn = -2; // You go left
  231.         }
  232.         
  233.         somebodyHit = ((srcSpriteDataPtr[kCurrentAction] == aKick ||
  234.             srcSpriteDataPtr[kCurrentAction] == aPunch ||
  235.             srcSpriteDataPtr[kCurrentAction] == aUppercut ||
  236.             srcSpriteDataPtr[kCurrentAction] == aJumpAttack ||
  237.             srcSpriteDataPtr[kCurrentAction] == aJumpPunch ||
  238.             srcSpriteDataPtr[kCurrentAction] == aJumpKick ||
  239.             srcSpriteDataPtr[kCurrentAction] == aProjectileShoot) ? TRUE : FALSE);
  240.         if(somebodyHit)
  241.         {
  242.             switch(srcSpriteDataPtr[kSpriteIDNum])
  243.             {
  244.                 case kPlayer1Sprite:
  245.                 case kComputer1Sprite:
  246.                     PlaySound(gP1SoundH[sGotHit], gSoundChanP1);
  247.                     break;
  248.                 case kPlayer2Sprite:
  249.                 case kComputer2Sprite:
  250.                     PlaySound(gP2SoundH[sGotHit], gSoundChanP2);
  251.                     break;
  252.             }
  253.             switch(srcSpriteDataPtr[kCurrentAction])
  254.             {
  255.                 case aKick:
  256.                 case aPunch:
  257.                 case aJumpAttack:
  258.                 case aJumpKick:
  259.                 case aJumpPunch:
  260.                 case aProjectileShoot:
  261.                 // swap h/v delta's
  262.                     dstSpriteP->horizMoveDelta = kWhipLashVelocity*dstDrxn;
  263.                     if(dstSpriteDataPtr[kCurrentAction] != aBlock)
  264.                     {
  265.                         dstSpriteHit = TRUE;
  266.                     }
  267.                     break;
  268.                 case aUppercut:
  269.                 // swap h/v delta's
  270.                     dstSpriteP->horizMoveDelta = kWhipLashVelocity*dstDrxn;
  271.                     if(dstSpriteDataPtr[kCurrentAction] != aBlock)
  272.                     {
  273.                         dstSpriteP->vertMoveDelta = -10*kWhipLashVelocity;
  274.                         dstSpriteHit = TRUE;
  275.                     }
  276.                     break;
  277.             }
  278.         }
  279.         somebodyHit = ((dstSpriteDataPtr[kCurrentAction] == aKick ||
  280.             dstSpriteDataPtr[kCurrentAction] == aPunch ||
  281.             dstSpriteDataPtr[kCurrentAction] == aUppercut ||
  282.             dstSpriteDataPtr[kCurrentAction] == aJumpAttack ||
  283.             dstSpriteDataPtr[kCurrentAction] == aJumpPunch ||
  284.             dstSpriteDataPtr[kCurrentAction] == aJumpKick ||
  285.             dstSpriteDataPtr[kCurrentAction] == aProjectileShoot) ? TRUE : FALSE);
  286.         if(somebodyHit)
  287.         {
  288.             switch(srcSpriteDataPtr[kSpriteIDNum])
  289.             {
  290.                 case kPlayer1Sprite:
  291.                 case kComputer1Sprite:
  292.                     PlaySound(gP1SoundH[sGotHit], gSoundChanP1);
  293.                     break;
  294.                 case kPlayer2Sprite:
  295.                 case kComputer2Sprite:
  296.                     PlaySound(gP2SoundH[sGotHit], gSoundChanP2);
  297.                     break;
  298.             }
  299.             switch(dstSpriteDataPtr[kCurrentAction])
  300.             {
  301.                 case aKick:
  302.                 case aPunch:
  303.                 case aJumpAttack:
  304.                 case aJumpKick:
  305.                 case aJumpPunch:
  306.                 case aProjectileShoot:
  307.                 // swap h/v delta's
  308.                     srcSpriteP->horizMoveDelta = kWhipLashVelocity*srcDrxn;
  309.                     if(srcSpriteDataPtr[kCurrentAction] != aBlock)
  310.                     {
  311.                         srcSpriteHit = TRUE;
  312.                     }
  313.                     break;
  314.                 case aUppercut:
  315.                 // swap h/v delta's
  316.                     srcSpriteP->horizMoveDelta = kWhipLashVelocity*srcDrxn;
  317.                     if(srcSpriteDataPtr[kCurrentAction] != aBlock)
  318.                     {
  319.                         srcSpriteP->vertMoveDelta = -10*kWhipLashVelocity;
  320.                         srcSpriteHit = TRUE;
  321.                     }
  322.                     break;
  323.             }
  324.         }
  325.         // Was anybody hurt?
  326.         // Only 1 hit per attack move!!!
  327.         if(flipFlop) // to counter the player 1/2 advantage
  328.         {
  329.             flipFlop = FALSE;
  330.             //goto FLIP_FLOP; // I did have this uncommented
  331.         }
  332.         else
  333.         {
  334.             flipFlop = TRUE;
  335.         }
  336.         
  337.         if(srcSpriteHit && srcSpriteDataPtr[kCurrentAction] != aGotHit
  338.                     && dstSpriteDataPtr[kCurrentAction] != aDying)
  339.         {
  340.             srcSpriteDataPtr[kCurrentAction] = aGotHit;
  341.             switch(dstSpriteDataPtr[kCurrentAction])
  342.             {
  343.                 case aPunch:
  344.                     damage = kPunchDamage;
  345.                     dstSpriteDataPtr[kCurrentAction] = aPostAttack;
  346.                     break;
  347.                 case aKick:
  348.                     damage = kKickDamage;
  349.                     dstSpriteDataPtr[kCurrentAction] = aPostAttack;
  350.                     break;
  351.                 case aUppercut:
  352.                     damage = kUppercutDamage;
  353.                     dstSpriteDataPtr[kCurrentAction] = aPostAttack;
  354.                     break;
  355.                 case aProjectileShoot:
  356.                     damage = kProjectileDamage;
  357.                     dstSpriteDataPtr[kCurrentAction] = aProjectileIdle;
  358.                     break;
  359.                 case aJumpAttack:
  360.                     damage = kJumpAttackDamage;
  361.                     dstSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
  362.                     break;
  363.                 case aJumpPunch:
  364.                     damage = kJumpPunchDamage;
  365.                     dstSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
  366.                     break;
  367.                 case aJumpKick:
  368.                     damage = kJumpKickDamage;
  369.                     dstSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
  370.                     break;
  371.                 default:
  372.                     break;
  373.             }
  374.             srcSpriteDataPtr[kSpriteLife] -= damage;
  375.             // Double damage code?
  376.             if(gSecretCode[kDoubleDamageCode])
  377.                 srcSpriteDataPtr[kSpriteLife] -= damage;
  378.         }
  379.         FLIP_FLOP:
  380.         // reset damage to zero
  381.         damage = 0;
  382.         if(dstSpriteHit && dstSpriteDataPtr[kCurrentAction] != aGotHit
  383.                     && dstSpriteDataPtr[kCurrentAction] != aDying)
  384.         {
  385.             dstSpriteDataPtr[kCurrentAction] = aGotHit;
  386.             switch(srcSpriteDataPtr[kCurrentAction])
  387.             {
  388.                 case aPunch:
  389.                     damage = kPunchDamage;
  390.                     // Double damage code?
  391.                     if(gSecretCode[kDoubleDamageCode])
  392.                         dstSpriteDataPtr[kSpriteLife] -= kPunchDamage;
  393.                     srcSpriteDataPtr[kCurrentAction] = aPostAttack;
  394.                     break;
  395.                 case aKick:
  396.                     damage = kKickDamage;
  397.                     srcSpriteDataPtr[kCurrentAction] = aPostAttack;
  398.                     break;
  399.                 case aUppercut:
  400.                     damage = kUppercutDamage;
  401.                     srcSpriteDataPtr[kCurrentAction] = aPostAttack;
  402.                     break;
  403.                 case aProjectileShoot:
  404.                     damage = kProjectileDamage;
  405.                     srcSpriteDataPtr[kCurrentAction] = aProjectileIdle;
  406.                     break;
  407.                 case aJumpAttack:
  408.                     damage = kJumpAttackDamage;
  409.                     srcSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
  410.                     break;
  411.                 case aJumpPunch:
  412.                     damage = kJumpPunchDamage;
  413.                     srcSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
  414.                     break;
  415.                 case aJumpKick:
  416.                     damage = kJumpKickDamage;
  417.                     srcSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
  418.                     break;
  419.                 default:
  420.                     break;
  421.             }
  422.             dstSpriteDataPtr[kSpriteLife] -= damage;
  423.             // Double damage code?
  424.             if(gSecretCode[kDoubleDamageCode])
  425.                 dstSpriteDataPtr[kSpriteLife] -= damage;
  426.         }
  427.     }
  428. }
  429.  
  430. /********** PlaySound ***************/
  431. /* March 1995 */
  432. void PlaySound(Handle soundHandle, SndChannelPtr sndChan)
  433. {
  434.     OSErr    err;
  435.     SndCommand    command;
  436.     SCStatus    theStatus;
  437.     long        offset;
  438.     
  439.     if(gSoundOff == TRUE) // accessed via secret menu
  440.         return;
  441.     if(soundHandle == NULL)
  442.         DoError(kNULLSoundHandle, TRUE);
  443.     //HLock(soundHandle); - I lock them ahead of time.
  444.     if(sndChan == NULL)
  445.         DoError(kNULLSoundChannel,TRUE);
  446.     if(SndChannelBusy(sndChan))
  447.     {
  448.         command.cmd = flushCmd;
  449.         command.param1 = command.param2 = 0;
  450.         err = SndDoImmediate( sndChan, &command);
  451.         if(err)
  452.             DoError(kCouldNotFlushSoundChannel, TRUE);
  453.         command.cmd = quietCmd;
  454.         command.param1 = command.param2 = 0;
  455.         err = SndDoImmediate( sndChan, &command);
  456.         if(err)
  457.             DoError(kCouldNotQuietSoundChannel, TRUE);
  458.     }
  459.     if(gSoundMax == TRUE) // accessed via a hidden menu
  460.     {
  461.         command.cmd = volumeCmd;
  462.         command.param1 = 0; // unused
  463.         command.param2 = 0x03000300; // 3X Full volume! whoa!
  464.         err = SndDoImmediate(sndChan, &command);
  465.         if(err != noErr)
  466.             DoError(kNeedSoundMgr3ForMegaVolume, TRUE);
  467.     }
  468.     if(gSoundMegaMax == TRUE) // accessed via a hidden menu
  469.     {
  470.         command.cmd = volumeCmd;
  471.         command.param1 = 0; // unused
  472.         command.param2 = 0x07000700; // 7X Full volume! ZOINKS!!!
  473.         err = SndDoImmediate(sndChan, &command);
  474.         if(err != noErr)
  475.             DoError(kNeedSoundMgr3ForMegaVolume, TRUE);
  476.     }
  477.     err = GetSoundHeaderOffset( (SndListHandle)soundHandle,&offset);
  478.     if(err != noErr)
  479.         DoError(kCouldNotGetSoundHeaderOffset, TRUE);
  480.     command.cmd = bufferCmd;
  481.     command.param1 = 0;
  482.     command.param2 = (long)(*soundHandle + offset);
  483.     err = SndDoImmediate( sndChan,&command);
  484.     if( err != noErr)
  485.         DoError(kSoundBufferError, TRUE);
  486. }
  487.  
  488. /********** PlaySound ***************/
  489. /* April 1996 */
  490. void LoopSound(Handle soundHandle, SndChannelPtr sndChan)
  491. {
  492.     OSErr    err;
  493.     SndCommand    command;
  494.     SCStatus    theStatus;
  495.     long        offset;
  496.     
  497.     if(gSoundOff == TRUE) // accessed via secret menu
  498.         return;
  499.     if(soundHandle == NULL)
  500.         DoError(kNULLSoundHandle, TRUE);
  501.     //HLock(soundHandle); - I lock them ahead of time.
  502.     if(sndChan == NULL)
  503.         DoError(kNULLSoundChannel,TRUE);
  504.     if(SndChannelBusy(sndChan))
  505.     {
  506.         return; // it's busy playing already!
  507.     }
  508.     err = GetSoundHeaderOffset( (SndListHandle)soundHandle,&offset);
  509.     if(err != noErr)
  510.         DoError(kCouldNotGetSoundHeaderOffset, TRUE);
  511.     command.cmd = bufferCmd;
  512.     command.param1 = 0;
  513.     command.param2 = (long)(*soundHandle + offset);
  514.     err = SndDoImmediate( sndChan,&command);
  515.     if( err != noErr)
  516.         DoError(kSoundBufferError, TRUE);
  517. }
  518.  
  519. /********** PlaySound ***************/
  520. /* March 1995 */
  521. void StopPlayingSound(SndChannelPtr sndChan)
  522. {
  523.     OSErr    err;
  524.     SndCommand    command;
  525.     
  526.     if(sndChan == NULL)
  527.         DoError(kNULLSoundChannel,TRUE);
  528.     if(SndChannelBusy(sndChan))
  529.     {
  530.         command.cmd = flushCmd;
  531.         command.param1 = command.param2 = 0;
  532.         err = SndDoImmediate( sndChan, &command);
  533.         if(err)
  534.             DoError(kCouldNotFlushSoundChannel, TRUE);
  535.         command.cmd = quietCmd;
  536.         command.param1 = command.param2 = 0;
  537.         err = SndDoImmediate( sndChan, &command);
  538.         if(err)
  539.             DoError(kCouldNotQuietSoundChannel, TRUE);
  540.     }
  541. }
  542.  
  543. /* CODE EXAMPLE #1 */
  544. short isPressed(unsigned short k)
  545. // k =  any keyboard scan code, 0-127
  546. {
  547.     unsigned char km[16];
  548.  
  549.     StefGetKeys;
  550.     return ( ( km[k>>3] >> (k & 7) ) & 1);
  551. }
  552.  
  553. void StartWaiting(void)
  554. {
  555.     Cursor    watchCurs;
  556.     CursHandle    watchCursH;
  557.     
  558.     watchCursH = GetCursor(watchCursor);
  559.     watchCurs = **watchCursH;
  560.     SetCursor(&watchCurs);
  561.     DisposeHandle((Handle)watchCursH);
  562. }
  563.  
  564. void StopWaiting(void)
  565. {
  566.     SetCursor(&qd.arrow);
  567. }